package main

import (
	"bufio"
	"encoding/csv"
	"errors"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"sort"
	"strconv"
	"time"
)

var lucky = [][]int{
	{2, 6, 16, 17, 28, 32, 11},
	{3, 6, 9, 21, 23, 30, 7},
}

type render struct {
	RedLucky1, RedLucky2, RedPrize1, RedPrize2, RedPrize      []int
	BlueLucky1, BlueLucky2, BluePrize1, BluePrize2, BluePrize int
}

func main() {
	http.HandleFunc("/", getPrize)

	port := "1234"

	log.Printf(fmt.Sprintf("About to listen on %s. Go to http://localhost:%s/", port, port))
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

func unlink() {
	os.Remove(getCsvFile())
}

func explainHtml() []int {
	// Request the HTML page.
	res, err := http.Get("https://kaijiang.500.com/ssq.shtml")
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}

	// Load the HTML document
	doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Fatal(err)
	}
	var prize []int
	//Find the review items
	doc.Find(".ball_box01 ul li").Each(func(i int, s *goquery.Selection) {
		// For each item found, get the band and title
		num, _ := strconv.Atoi(s.Text())
		prize = append(prize, num)
	})
	return prize

}

// get prize number.
func getPrize(w http.ResponseWriter, r *http.Request) {
	if r.FormValue("refresh") == "true" {
		unlink()
	}
	var prize []int
	var err error

	if prize, err = rcsv(); err != nil {
		prize = explainHtml()
		wcsv(prize)
	}

	rr := render{}
	blueIndex := len(prize) - 1
	rr.BluePrize = prize[blueIndex]
	rr.RedPrize = append(prize[0:blueIndex])

	lucky1 := lucky[0]
	lucky2 := lucky[1]
	rr.BlueLucky1 = lucky1[6]
	rr.RedLucky1 = lucky1[0:6]
	rr.BlueLucky2 = lucky2[6]
	rr.RedLucky2 = lucky2[0:6]

	if rr.BlueLucky1 == rr.BluePrize {
		rr.BluePrize1 = rr.BlueLucky1
	}

	if rr.BlueLucky2 == rr.BluePrize {
		rr.BluePrize2 = rr.BlueLucky2
	}

	for _, v := range rr.RedPrize {
		if in(v, rr.RedLucky1) {
			rr.RedPrize1 = append(rr.RedPrize1, v)
		}
		if in(v, rr.RedLucky2) {
			rr.RedPrize2 = append(rr.RedPrize2, v)
		}
	}
	renderHtml(w, rr)
}

func renderHtml(w io.Writer, data interface{}) {
	t, err := template.ParseFiles("./views/index.html")
	if err != nil {
		log.Fatal(err)
	}
	err = t.Execute(w, data)
	if err != nil {
		log.Fatal(err)
	}
}

func in(target int, stack []int) bool {
	sort.Ints(stack)
	index := sort.SearchInts(stack, target)
	if index < len(stack) && stack[index] == target {
		return true
	}
	return false
}
func getCsvFile() string {
	year, month, day := time.Now().Date()
	return fmt.Sprintf("prize/%d%d%d.csv", year, month, day)
}

func rcsv() ([]int, error) {
	if !fileExist(getCsvFile()) {
		return nil, errors.New("not found csv file")
	}
	file, err := os.Open(getCsvFile())
	if err != nil {
		fmt.Println("open file is failed, err: ", err)
	}
	defer file.Close()
	reader := csv.NewReader(bufio.NewReader(file))
	line, err := reader.ReadAll()
	var prize []int
	for _, v := range line[0] {
		vs, _ := strconv.Atoi(v)
		prize = append(prize, vs)
	}
	return prize, err
}

func wcsv(data []int) {
	file, err := os.OpenFile(getCsvFile(), os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		fmt.Println("open file is failed, err: ", err)
	}
	defer file.Close()
	// 写入UTF-8 BOM，防止中文乱码
	//file.WriteString("\xEF\xBB\xBF")
	file.Seek(0, io.SeekEnd)
	w := csv.NewWriter(file)
	var datas []string
	for _, v := range data {
		datas = append(datas, strconv.Itoa(v))
	}
	w.Write(datas)
	// 写文件需要flush，不然缓存满了，后面的就写不进去了，只会写一部分
	w.Flush()
}

func fileExist(path string) bool {
	_, err := os.Lstat(path)
	return !os.IsNotExist(err)
}
